package controller;

import api.WxPayApi;
import com.google.common.collect.ImmutableMap;
import common.pojo.CommonResult;
import common.utils.CommomRandom;

import httpclient.HttpClientUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import pojo.PayInfo;
import pojo.form.PayInfoAddForm;
import service.PayInfoService;
import service.cfg.WxCfg;
import utils.JsonUtil;
import utils.PayUtils;
import utils.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * Created by asus on 2018/10/27.
 */
@Controller
@RequestMapping(value = "/pay")
public class PayController extends ManagerBaseController {

    @Autowired
    WxPayApi wxPayApi;
    @Autowired
    WxCfg wxCfg;
    @Autowired
    PayInfoService payInfoService;
    private final Logger log = LoggerFactory.getLogger(PayController.class);


    /**
     * 统一下单
     *
     * @param request amount  支付金额
     *                sessionId  验证用户身份获取openid
     *                notifyUrl   回调更新路径
     *                orderCode  订单号
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/unifiedOrder", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult unifiedOrder(HttpServletRequest request) throws Exception {
        Map paramMap = parseRequestParamMap(request);
        if (StringUtils.isBlank(paramMap.get("openId").toString())) {
            return CommonResult.returnFailsWrapper("未查询到用户信息");
        }
        if (StringUtils.isBlank(paramMap.get("orderCode").toString())) {
            return CommonResult.returnFailsWrapper("请传入orderCode");
        }
        if (StringUtils.isBlank(paramMap.get("notifyUrl").toString())) {
            return CommonResult.returnFailsWrapper("请传入notifyUrl");
        }
        if (StringUtils.isBlank(paramMap.get("amount").toString())) {
            return CommonResult.returnFailsWrapper("请传入支付金额");
        }
        String orderCode = paramMap.get("orderCode").toString();
        String notifyUrl = paramMap.get("notifyUrl").toString();
        String amount = paramMap.get("amount").toString();
        String openId = paramMap.get("openId").toString();
        //查询本地订单是否存在 or  支付状态
        PayInfo payInfo = payInfoService.getPayInfo(orderCode);
        if (payInfo != null) {
            //存在订单
            if (payInfo.getIsPay() == 1) {
                //本地订单已支付//更新商城订单
                CommonResult commonResult = HttpClientUtils.post(notifyUrl, ImmutableMap.of("orderCode", orderCode, "transactionId", payInfo.getTransactionId()));
                if (commonResult.isNotSuccess()) {
                    log.warn("----订单--" + paramMap.get("orderCode") + "更新异常");
                    return CommonResult.returnFailsWrapper("订单更新异常，请联系管理员");
                }
                commonResult.setMessage("SUCCESS");
                return commonResult;
            } else {
                //微信回调时没有更新或取消支付 更新失败
                //payInfo存在且未支付//此时验证商户平台是否存在订单
                String msg = queryOrder(paramMap.get("orderCode").toString());
                if ("SUCCESS".equals(msg)) {
                    //商户平台已经支付//更新商城订单
                    CommonResult commonResult = HttpClientUtils.post(notifyUrl, ImmutableMap.of("orderCode", orderCode, "transactionId", payInfo.getTransactionId()));
                    if (commonResult.isNotSuccess()) {
                        log.warn("----订单--" + paramMap.get("orderCode") + "更新异常");
                        return CommonResult.returnFailsWrapper("订单更新异常，请联系管理员");
                    }
                    commonResult.setMessage("SUCCESS");
                    return commonResult;
                } else {
                    //调用统一下单返回支付信息
                    return this.unifiedOrder(amount, openId, orderCode);
                }
            }
        } else {
            //调用统一下单//创建本地未支付订单
            int addNum = payInfoService.addPayInfo(new PayInfoAddForm(orderCode, NumberUtils.toDouble(amount), 0, "weixin", new Date(), notifyUrl, openId));
            if (addNum <= 0) {
                log.warn("--本地订单添加失败------");
                return CommonResult.returnFailsWrapper("本地订单创建失败");
            }
            return this.unifiedOrder(amount, openId, orderCode);
        }
    }

    //查询订单是否存在并且是否已支付
    public String queryOrder(String orderCode) throws Exception {
        Map map = wxPayApi.orderQuery(orderCode);
        if ("SUCCESS".equals(map.get("result_code").toString()) && "SUCCESS".equals(map.get("return_code").toString())) {
            if (StringUtils.isNotBlank(map.get("trade_state").toString())) {
                if ("SUCCESS".equals(map.get("trade_state").toString())) {
                    //更新pay_info
                    payInfoService.updatePayInfo(orderCode, map.get("transaction_id").toString(), JsonUtil.toJson(map), NumberUtils.toInt(map.get("total_fee").toString()));
                    //该订单已支付成功
                    return "SUCCESS";
                }
            } else {
                return "FAIL";
            }
        }
        return "FAIL";
    }

    //统一下单返回支付信息
    public CommonResult unifiedOrder(String amount, String openId, String orderCode) {
        Map map = null;
        try {
            map = wxPayApi.unifiedOrder(this.getIntNum(amount), openId, orderCode);
            String timeStamp = PayUtils.getTimeStamp();// 当前时间戳
            String nonceStr = PayUtils.getRandomStr(20);// 不长于32位的随机字符串
            log.info("--unifiedOrder---" + JsonUtil.toJson(map));
            if ("SUCCESS".equals(map.get("return_code")) && "SUCCESS".equals(map.get("result_code"))) {
                SortedMap<String, Object> signMap = new TreeMap<String, Object>();// 自然升序map
                signMap.put("appId", wxCfg.getApp_id());
                signMap.put("package", "prepay_id=" + map.get("prepay_id"));
                signMap.put("timeStamp", timeStamp);
                signMap.put("nonceStr", nonceStr);
                signMap.put("signType", "MD5");
                String sign = PayUtils.getSign(signMap, wxCfg.getApi_key());
                signMap.put("paySign", sign);
                payInfoService.updatePrepay_id(map.get("prepay_id").toString(),orderCode);
                return CommonResult.returnDataWrapper(signMap);
            } else {
                return CommonResult.returnFailsWrapper(map.get("return_msg").toString());
            }
        } catch (Exception e) {
            log.warn("-unifiedOrder-fail--" + e.toString());
        }
        return CommonResult.returnFailsWrapper(map.get("return_msg").toString());
    }


    public String getIntNum(String amount) {
        try {
            Double dou = NumberUtils.toDouble(amount) * 100;
            int num =  dou.intValue();
            return ""+num+"";
        } catch (Exception e) {
            log.warn(" --- amount转换异常 --");
        }
        return "";
    }

    public String getIntNum2(String amount) {
        try {
            Double dou = NumberUtils.toDouble(amount);
            int num =  dou.intValue();
            return ""+num+"";
        } catch (Exception e) {
            log.warn(" --- amount转换异常 --");
        }
        return "";
    }

    @RequestMapping(value = "/refund",method = RequestMethod.POST)
    @ResponseBody
    public CommonResult refund(HttpServletRequest request){
        Map paramMap = parseRequestParamMap(request);
        if (StringUtils.isBlank(paramMap.get("orderCode").toString())) {
            return CommonResult.returnFailsWrapper("请传入orderCode");
        }
        if (StringUtils.isBlank(paramMap.get("amount").toString())) {
            return CommonResult.returnFailsWrapper("请传入支付金额");
        }
        String orderCode = paramMap.get("orderCode").toString();
        Double amount = NumberUtils.toDouble(paramMap.get("amount").toString());
        PayInfo payInfo = payInfoService.getPayInfo(orderCode);
        if(payInfo==null){
            return CommonResult.returnFailsWrapper("订单信息不存在");
        }
        if(payInfo.getIsPay()==0){
            return CommonResult.returnFailsWrapper("该订单未支付");
        }
        if(amount>payInfo.getTotalFee()){
            return CommonResult.returnFailsWrapper("退款金额大于实际支付金额");
        }
        String refundCode = CommomRandom.buildRandomStr(8);//订单号
        String des=paramMap.get("des").toString();
        if(StringUtils.isBlank(des)){
            des="商品退款";
        }
        Map map=null;
        try {
           map = wxPayApi.refund(orderCode,refundCode, String.valueOf(payInfo.getTotalFee().intValue()),this.getIntNum(amount.toString()),des);
           log.warn(JsonUtil.toJson(map));
           if("SUCCESS".equals(map.get("return_code").toString()) && "SUCCESS".equals(map.get("result_code").toString())){
               payInfoService.refund(orderCode,amount,refundCode);
               return CommonResult.returnDataWrapper("success");
           }else {
               return CommonResult.returnFailsWrapper(map.get("err_code").toString()+map.get("err_code_des"));
           }
         } catch (Exception e) {
             log.warn("--refund-e- "+e.toString());
        }
        return CommonResult.returnFailsWrapper("退款失败");
    }

    @RequestMapping(value = "/refunds",method = RequestMethod.POST)
    @ResponseBody
    public CommonResult refunds(HttpServletRequest request){
        String refundCode = CommomRandom.buildRandomStr(8);//订单号

        Map map=null;
        try {
            map = wxPayApi.refund("20190128114252194381679",refundCode, "4500",this.getIntNum("45"),"退款");
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.warn(JsonUtil.toJson(map));

        return CommonResult.returnDataWrapper();
    }


    @RequestMapping(value = "/query",method = RequestMethod.GET)
    @ResponseBody
    public void queryOrder(){
        try {
            Map map = wxPayApi.orderQuery("2018121731883279");
            System.out.println(JsonUtil.toJson(map));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
